package td3.model;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Enumeration;

import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.xml.serialize.OutputFormat;
import org.apache.xml.serialize.XMLSerializer;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;

public class ContactFacility {
	Document dom;

	public ContactTreeModel parse(File file, ContactTreeModel contacts)
			throws SAXException, FileNotFoundException, IOException {
		String xmlReaderClassName = "org.apache.xerces.parsers.SAXParser";
		XMLReader xr = XMLReaderFactory.createXMLReader(xmlReaderClassName);
		ContactHandler handler = new ContactHandler(contacts);
		xr.setContentHandler(handler);
		xr.setErrorHandler(handler);

		FileReader r = new FileReader(file);
		xr.parse(new InputSource(r));
		return handler.getContactTreeModel();
	}

	public String writeToXml(TreeNode root) throws Exception {
		String xml = "";
		createDocument();
		createDOMTree((DefaultMutableTreeNode) root);
		xml = documentToString();
		return xml;
	}

	private void createDocument() throws ParserConfigurationException {
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db = dbf.newDocumentBuilder();
		dom = db.newDocument();
	}

	private String documentToString() {
		OutputFormat format = new OutputFormat(dom);
		format.setIndenting(true);
		StringWriter stringWriter = new StringWriter();
		XMLSerializer serializer = new XMLSerializer(stringWriter, format);
		try {
			serializer.serialize(dom);
		} catch (Exception e) {
			e.printStackTrace();
		}
		String xml = stringWriter.toString();
		return xml;
	}

	private void createDOMTree(DefaultMutableTreeNode root) throws Exception {
		Element rootEle = dom.createElement("contacts");
		dom.appendChild(rootEle);

		@SuppressWarnings("unchecked")
		Enumeration<DefaultMutableTreeNode> children = root.getFirstChild()
				.children();
		if (children != null) {
			while (children.hasMoreElements()) {
				Element newElement = createChild(children);
				rootEle.appendChild(newElement);
			}
		}
	}

	private Element createChild(Enumeration<DefaultMutableTreeNode> children)
			throws Exception {
		Element newElement;
		DefaultMutableTreeNode nextElement = children
				.nextElement();
				if (nextElement.getUserObject() instanceof Contact) {
					newElement = createContactElement(nextElement);
				} else {
					newElement = createCategoryElement(nextElement);
				}
		return newElement;
	}

	private Element createCategoryElement(
			DefaultMutableTreeNode categoryTreeNode) throws Exception {
		Element categoryElement = dom.createElement(categoryTreeNode
				.getUserObject().toString());

		@SuppressWarnings("unchecked")
		Enumeration<DefaultMutableTreeNode> children = categoryTreeNode
				.children();
		if (children != null) {
			while (children.hasMoreElements()) {
				Element newElement = createChild(children);
				categoryElement.appendChild(newElement);
			}
		}
		return categoryElement;
	}

	private Element createContactElement(DefaultMutableTreeNode contactTreeNode)
			throws Exception {
		if (contactTreeNode.getUserObject() instanceof Contact) {
			Contact contact = (Contact) contactTreeNode.getUserObject();
			Element contactElement = dom.createElement("contact");

			Element nomElement = dom.createElement("nom");
			Text nomText = dom.createTextNode(contact.getNom());
			nomElement.appendChild(nomText);
			contactElement.appendChild(nomElement);

			Element mailElement = dom.createElement("mail");
			Text mailText = dom.createTextNode(contact.getMail());
			mailElement.appendChild(mailText);
			contactElement.appendChild(mailElement);

			Element iconeElement = dom.createElement("icone");
			Text iconeText = dom.createTextNode(contact.getIcone());
			iconeElement.appendChild(iconeText);
			contactElement.appendChild(iconeElement);

			return contactElement;
		} else {
			throw new Exception("Node is not a Contact");
		}
	}

}
